package kinectData;

import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.vecmath.Point3d;

import kinectData.models.AccelerometerData;

/**
 * View for plotting accelerometer data.
 * 
 * @author Markus
 */
public class AccelerometerView extends JPanel {

	private static final long serialVersionUID = 1L;
	private final int TIME_FRAME_WINDOW = 10000;
	private JFrame jf;
	private ArrayList<AccelerometerData> accData = new ArrayList<AccelerometerData>();
	private String mac;
	private int x = 0, accX = 0, accY = 0, accZ = 0;

	public AccelerometerView(String mac, int xPos, int yPos) {
		super();
		this.jf = new JFrame(mac);
		this.mac = mac;
		jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		jf.setSize(320, 260);
		jf.setLocation(xPos, yPos);
		jf.add(this);
		jf.setVisible(true);
	}

	public synchronized void paint(Graphics g) {
		g.clearRect(0, 0, this.getWidth(), this.getHeight());
		g.setColor(Color.white);
		g.fillRect(0, 0, this.getWidth(), this.getHeight());
		g.setColor(Color.black);
		g.drawLine(10, this.getHeight() / 2, this.getWidth() - 10, this.getHeight() / 2);
		g.drawLine(10, this.getHeight() - 10, 10, 10);
		if (!accData.isEmpty()) {
			float pixelsPerMillisecond = TIME_FRAME_WINDOW / (this.getWidth() - 20);
			long startTime = accData.get(0).getTrackingTime();
			double maxData = -1000.d;
			double minData = 1000.d;
			// Update the min and max data point.
			for (AccelerometerData a : accData) {
				Point3d p = a.getDataPoint();
				if (p != null) {
					// All of the following may be true.
					if (p.x < minData) {
						minData = p.x;
					} 
					if (p.x > maxData) {
						maxData = p.x;
					}
					if (p.y < minData) {
						minData = p.y;
					} 
					if (p.y > maxData) {
						maxData = p.y;
					}
					if (p.z < minData) {
						minData = p.z;
					}
					if (p.z > maxData) {
						maxData = p.z;
					}
				}
			}
			// Iterate over the set again to scale the data to fit the graph.
			maxData = Math.max(Math.abs(maxData), Math.abs(minData));
			double pixelPerAcceleration = ((this.getHeight() - 20) / 2) / maxData;
			for (AccelerometerData a : accData) {
				Point3d p = a.getDataPoint();
				if (p != null) {
					int prevAccX = accX, prevAccY = accY, prevAccZ = accZ;
					x = (int) ((a.getTrackingTime() - startTime) / pixelsPerMillisecond) + 10;
					accX = (int) (p.x * pixelPerAcceleration) + this.getHeight() / 2  + 10;
					accY = (int) (p.y * pixelPerAcceleration) + this.getHeight() / 2  + 10;
					accZ = (int) (p.z * pixelPerAcceleration) + this.getHeight() / 2 + 10;
					g.setColor(Color.red);
					g.drawLine(x, prevAccX, x, accX);
					g.setColor(Color.blue);
					g.drawLine(x, prevAccY, x, accY);
					g.setColor(Color.green);
					g.drawLine(x, prevAccZ, x, accZ);
				}
			}
		}
	}
	
	public void closeView(){
		jf.setVisible(false);
	}

	public synchronized void addData(AccelerometerData data) {
		accData.add(data);
		int lastIndexAboveTimeFrame = 0;
		// Limit the number of frames in the scene by removing data at points over the time frame. 
		for (int i = 0; i < accData.size(); i++) {
			if (data.getTrackingTime() - accData.get(i).getTrackingTime() > TIME_FRAME_WINDOW) {
				lastIndexAboveTimeFrame = i;
			}
		}
		// Remove old data from the head up to the index that is above the time frame.
		for (int i = 0; i < lastIndexAboveTimeFrame; i++) {
			accData.remove(0);
		}
		this.repaint();
	}

	public String getMac() {
		return mac;
	}
}
